using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public interface IEventArgv
{

}

public struct EmptyEvent : IEventArgv
{

}

public struct EventArgv<T> : IEventArgv
{
    public T a;
}

public struct EventArgv<T1,T2> : IEventArgv
{
    public T1 a;public T2 b;
}

public struct EventArgv<T1,T2,T3> : IEventArgv
{
    public T1 a;public T2 b; public T3 c;
}

public struct EventArgv<T1,T2,T3,T4> : IEventArgv
{
    public T1 a; public T2 b; public T3 c; public T4 d;
}

public class EventDispatchManager : MonoBehaviour
{
    public static EventDispatchManager Instance { get; private set; }

    Dictionary<int,System.Action<IEventArgv>> mEvents = new Dictionary<int,System.Action<IEventArgv>>();

    private void Awake()
    {
        Instance = this;
        mEvents.Clear();
    }

    private void OnDestroy()
    {
        Instance = null;
    }

    public void AddEvent(int eventId,System.Action<IEventArgv> action)
    {
        if(!mEvents.ContainsKey(eventId))
        {
            mEvents[eventId] = action;
        }
        else
        {
            mEvents[eventId] = (System.Action<IEventArgv>)System.Delegate.Combine(action, mEvents[eventId]);
        }
    }

    public void RemoveEvent(int eventId,System.Action<IEventArgv> action)
    {
        if(mEvents.ContainsKey(eventId))
        {
            var eventSet = (System.Action<IEventArgv>)System.Delegate.Remove(mEvents[eventId], action);
            if(null == eventSet)
            {
                mEvents.Remove(eventId);
            }
            else
            {
                mEvents[eventId] = eventSet;
            }
        }
    }

    public void SendEvent(int eventId)
    {
        if (mEvents.ContainsKey(eventId))
        {
            mEvents[eventId]?.Invoke(new EmptyEvent());
        }
    }

    public void SendEvent<T>(int eventId,T a)
    {
        if (mEvents.ContainsKey(eventId))
        {
            mEvents[eventId]?.Invoke(new EventArgv<T> {a = a });
        }
    }

    public void SendEvent<T1,T2>(int eventId, T1 a,T2 b)
    {
        if (mEvents.ContainsKey(eventId))
        {
            mEvents[eventId]?.Invoke(new EventArgv<T1,T2> { a = a,b=b });
        }
    }

    public void SendEvent<T1, T2,T3>(int eventId, T1 a, T2 b,T3 c)
    {
        if (mEvents.ContainsKey(eventId))
        {
            mEvents[eventId]?.Invoke(new EventArgv<T1, T2,T3> { a = a, b = b,c=c });
        }
    }

    public void SendEvent<T1, T2, T3,T4>(int eventId, T1 a, T2 b, T3 c,T4 d)
    {
        if (mEvents.ContainsKey(eventId))
        {
            mEvents[eventId]?.Invoke(new EventArgv<T1, T2, T3,T4> { a = a, b = b, c = c,d=d});
        }
    }
}
